home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d11 / vgafx101.arc / FLASH1.ASM < prev    next >
Assembly Source File  |  1989-12-01  |  30KB  |  851 lines

  1. Comment |
  2.  
  3.     This module demonstrates special effect attributes in attribute
  4.     control mode 1 and provides several user-callable functions for
  5.     attribute manipulation.  The callable functions are:
  6.  
  7.       flash_init          Initializes system; call before using others
  8.       flash_term          Restores system; call before terminating
  9.       set_flash_rate      Sets number of timer ticks between palettes
  10.       set_delta           Sets number added to current palette per change
  11.       load_palettes       Loads all 16 palettes into VGA
  12.       reset_palettes      Resets to 16 base palettes
  13.       pulse_color         Creates a pulsing color, 16 palettes
  14.       pulse_color_partial Creates a pulsing color, < 16 palettes
  15.       set_color           Defines a color for one attibute, all 16 palettes
  16.       set_color_partial   Defines a color for one attibute, < 16 palettes
  17.       grade_color         Creates a graded color over 16 palettes
  18.       grade_color_partial Creates a grade color over < 16 palettes
  19.       blinker             Copies BG colors into FG, for simulated blinking
  20.  
  21.     Additionally, one data item is public to the user.  FLASH_ENABLED
  22.     is a byte variable; a zero value here disables palette changes,
  23.     effectively "freezing" the colors currently displayed.
  24.  
  25.     The module is designed for linking into a COM program.  All functions
  26.     are NEAR calls and assume DS=ES, except for TIMER_INT, which is an
  27.     interrupt intercept and assumes that CS=DS=ES.
  28.  
  29.     The module prologues provide greater detail on function requirements
  30.     and register use.
  31.  
  32.     Tested under MASM 5.1 and OPTASM 1.5.
  33.  
  34.     Prep:
  35.         masm flash0;
  36.            -or-
  37.         optasm flash0;
  38.         link hostprog+flash0;
  39.         exe2bin hostprog
  40.  
  41.     Uncopyrighted material, use freely
  42.     By Chris Dunford/Cove Software (CompuServe 76703,2002; tel. 301/992-9371)
  43.  
  44.     Version history:
  45.         1.01 10/29/89
  46.             Substituted an "official" test for VGA presence
  47.  
  48.         1.00 10/09/89
  49.  
  50. |
  51.  
  52. public flash_init,flash_term
  53. public pulse_color,pulse_color_partial
  54. public grade_color,grade_color_partial
  55. public set_color,set_color_partial
  56. public blinker
  57. public load_palettes,reset_palettes
  58. public set_flash_rate,set_delta
  59. public flash_enabled
  60.  
  61. ; This equate determines whether TIMER_INT uses BIOS or register-level
  62. ; programming to accomplish palette changes.  Set to 0 for register-level,
  63. ; any non-zero value for BIOS level.
  64. USE_BIOS equ 0
  65.  
  66. ; Macro accesses the palette control video BIOS function (fn 10H)
  67. ; Call: palctrl subfunction
  68. palctrl macro fn
  69.         mov ax,10h shl 8 + fn
  70.         int 10h
  71. endm
  72.  
  73. ; Structure for storing graded color scaling data.  See CALC_SCALE_FACTORS.
  74. scale_factors struc
  75. incr        db ?
  76. xs_count    db ?
  77. xs_incr_val db ?
  78. scale_factors ends
  79.  
  80. ; Subfunctions (AL values) for palette control function
  81. _SET_PALREGS           equ 2
  82. _GET_PALREGS           equ 9
  83. _SET_COLOR             equ 10h
  84. _SET_DACS              equ 12h
  85. _SET_ATR_SELECT_STATE  equ 13h
  86. _GET_DACS              equ 17h
  87. _GET_ATR_SELECT_STATE  equ 1AH
  88.  
  89.  
  90. code segment word public 'code'
  91. assume cs:code,ds:code,es:code
  92.  
  93. ; ========================================================================
  94. ;                          DATA FOR VGA MANIPULATION
  95. ; ========================================================================
  96.  
  97. ; Storage for the original 16 palettes
  98. origpals db 16*16*3 dup (0)     ; 16 palettes, 16 colors each, 3 RGB values per
  99.  
  100. ; Additional saved state info
  101. orig_mode           db ?                ; Original attr control mode
  102. orig_color_select   db ?                ; Original color select reg value
  103.  
  104. ; Storage for the augmented palettes
  105. newpals  db 16*16*3 dup (0)
  106.  
  107. ; Storage for the 16 palatte registers + overscan reg
  108. palregs db 17 dup (0)
  109.  
  110. ; The 16 new palette register contents we will use, plus overscan
  111. newpalregs db 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0
  112.  
  113. ; Storage for factors used to scale one color to another over
  114. ; fifteen palettes.  Don't separate or re-order; module assumes
  115. ; that the R/G/B records are contiguous and in that order.
  116. red_scale   scale_factors <>
  117. green_scale scale_factors <>
  118. blue_scale  scale_factors <>
  119.  
  120. ; Color definitions for our 16 base colors.  16 colors, 3 RGB values each
  121. new_base_pal label byte
  122. .radix 16
  123.         db 00,00,00    ; Color 0 (normally black)
  124.         db 00,00,2A    ; Color 1 (blue)
  125.         db 00,2A,00    ; Color 2 (green)
  126.         db 00,2A,2A    ; Color 3 (cyan)
  127.         db 2A,00,00    ; Color 4 (red)
  128.         db 2A,00,2A    ; Color 5 (magenta)
  129.         db 2A,2A,00    ; Color 6 (brown)
  130.         db 2A,2A,2A    ; Color 7 (white)
  131.  
  132.         db 00,00,15    ; Color 8 (some very dark color)
  133.         db 00,00,33    ; Color 9 (brt blue)
  134.         db 00,33,00    ; Color 10 (brt green)
  135.         db 00,33,33    ; Color 11 (brt cyan)
  136.         db 33,00,00    ; Color 12 (brt red)
  137.         db 33,00,33    ; Color 13 (brt magenta)
  138.         db 33,33,00    ; Color 14 (yellow)
  139.         db 33,33,33    ; Color 15 (brt white)
  140. .radix 10
  141.  
  142. ; Flasher data
  143. flash_enabled       db 1                ; 0=disabled, 1=enabled
  144. flash_reset_count   dw 1                ; Flash rate, in timer ticks
  145. count               dw 9                ; Remaining countdown
  146. pal_select          db 0                ; Current palette #
  147. delta               db 1                ; # palettes to change per flash
  148.  
  149. ; Storage for original timer vector
  150. oldtimer label dword
  151. tickvec_lo dw ?
  152. tickvec_hi dw ?
  153.  
  154. ; ========================================================================
  155. ;                              CALLABLE FUNCTIONS
  156. ; ========================================================================
  157.  
  158.  
  159. ; ----- flash_init ------------------------------------------------------
  160. ; This function must be called to initialize the system for controlled
  161. ; flashing.  It accomplishes several tasks:
  162. ;
  163. ;    - Saves the 16 palette registers in palregs
  164. ;    - Gets the current 256 colors (4 palettes) to origpals
  165. ;    - Duplicates palette 0 in palette 1 and loads it into the VGA
  166. ;    - Installs the timer intercept
  167. ;
  168. ; On exit, flashing is set up, but nothing is actually flashing (because
  169. ; palettes 0 and 1 are identical).
  170. ;
  171. ; Returns CF=1 if no VGA detected.  All regs except segregs may be destroyed.
  172. ;
  173. flash_init:
  174.  
  175. ; Test for VGA presence
  176.         mov ax,1A00h                    ; Get video display combination
  177.         int 10h
  178.         cmp al,1AH                      ; Supported function?
  179.         jne no_VGA                      ; No, no VGA BIOS
  180.         cmp bl,7                        ; VGA/mono?
  181.         je got_vga                      ; Yes
  182.         cmp bl,8                        ; VGA/color?
  183.         je got_VGA                      ; Yes
  184. no_VGA:     stc                         ; No VGA
  185.             jmp fi_exit
  186.  
  187. ; Save current attribute control mode & color select reg
  188. got_VGA:
  189.         palctrl _GET_ATR_SELECT_STATE   ; A VGA-only function
  190.         mov orig_mode,bl
  191.         mov orig_color_select,bh
  192.  
  193. ; Save the 16 current palette registers into palregs; reset the
  194. ; palette registers to contain 16 "standard" 4-bit colors.
  195.         ; Get current regs
  196.         mov dx,offset palregs
  197.         palctrl _GET_palregs
  198.  
  199.         ; Continue to use the current border color
  200.         mov al,palregs+16
  201.         and al,0FH
  202.         mov newpalregs+16,al
  203.  
  204.         ; Set new palregs
  205.         mov dx,offset newpalregs
  206.         palctrl _SET_PALREGS
  207.  
  208. ; Save the original DAC color registers (256 colors) in origpals
  209.         xor bx,bx                       ; Start with register 0
  210.         mov cx,256                      ; 256 registers
  211.         mov dx,offset origpals          ; Where to put 'em
  212.         palctrl _GET_DACS
  213.  
  214. ; Create 16 standard palettes in newpals and send them to the VGA
  215.         call dupe_palette0
  216.         mov dx,offset newpals
  217.         call set_colors
  218.  
  219. ; Set attribute control mode 1
  220.         mov bx,100h
  221.         palctrl _SET_ATR_SELECT_STATE
  222.  
  223. ; Save/set the timer intercept
  224.         push es
  225.         mov ax,3508h
  226.         int 21h
  227.         mov tickvec_lo,bx
  228.         mov tickvec_hi,es
  229.         pop es
  230.  
  231.         mov dx,offset timer_int
  232.         mov ax,2508h
  233.         int 21h
  234.  
  235.         clc
  236.  
  237. fi_exit:
  238.         ret
  239.  
  240. ; ----- flash_term -----------------------------------------------------
  241. ; This function must be called for cleanup when program terminates:
  242. ;    - Deactivates the timer intercept
  243. ;    - Restores the original VGA state
  244. ; AX,BX,CX,DX destroyed
  245. ;
  246. flash_term:
  247.  
  248. ; Clear the timer interrupt
  249.         push ds
  250.         lds dx,oldtimer
  251.         mov ax,2508h
  252.         int 21h
  253.         pop ds
  254.  
  255. ; Restore original palette registers and video DAC color registers
  256.         mov dx,offset palregs
  257.         palctrl _SET_PALREGS
  258.         mov dx,offset origpals
  259.         call set_colors
  260.  
  261. ; Restore original attribute control mode
  262.         xor bl,bl                       ; Subfn to set control mode
  263.         mov bh,orig_mode
  264.         palctrl _SET_ATR_SELECT_STATE
  265.  
  266. ; Go back to palette 0
  267.         mov bl,1                        ; Subfn to set color select reg
  268.         mov bh,orig_color_select        ; Value to set
  269.         palctrl _SET_ATR_SELECT_STATE
  270.  
  271.         ret
  272.  
  273. ; ----- set_flash_rate ------------------------------------------------
  274. ; Reset the flash rate to the number of ticks in AX (18/sec); i.e.,
  275. ; the palette will change every AX ticks.  All regs preserved.
  276. ;
  277. set_flash_rate:
  278.         cli
  279.         mov flash_reset_count,ax
  280.         mov count,ax
  281.         sti
  282.         ret
  283.  
  284. ; ----- set_delta ------------------------------------------------------
  285. ; Set the increment value for palette changes.  When the ticker
  286. ; ticks down and the palette is to be changed, the timer ISR will
  287. ; add/subtract this number to the current palette number.  With a
  288. ; higher delta, you can flash more rapidly.  E.g., with delta=1,
  289. ; the palettes change 0,1,2,3,...,15.  With delta=3, the palette
  290. ; changes are 1,3,6,9,12,15.  If delta=0, only palette 0 is used.
  291. ;
  292. ; AX destroyed.
  293. ;
  294. set_delta:
  295.         push cx
  296.         and al,15
  297.         mov cl,al
  298.         cli
  299.         mov delta,al
  300.  
  301.         ; Ensure that the selected palettes will
  302.         ; be multiples of the delta
  303.         or cl,cl
  304.         jnz SD20
  305.             xor al,al
  306.             jmp SD50
  307.  
  308. SD20:
  309.             mov al,pal_select
  310.             xor ah,ah
  311.             div cl
  312.             mul cl
  313.  
  314. SD50:
  315.         mov pal_select,al
  316.         sti
  317.         pop cx
  318.         ret
  319.  
  320. ; ----- load_palettes -------------------------------------------------
  321. ; Load the set of palettes in NEWPALS into the VGA.
  322. ;
  323. load_palettes:
  324.         mov dx,offset newpals
  325.         call set_colors
  326.         ret
  327.  
  328. ; ----- reset_palettes ----------------------------------------------
  329. ; This function resets the VGA to 16 copies of the "standard" palette.
  330. ;
  331. reset_palettes:
  332.         call dupe_palette0
  333.         call load_palettes
  334.         ret
  335.  
  336. ; ----- pulse_color_partial ----------------------------------------
  337. ; Creates a "pulsing" attribute.  This is one whose intensity increases
  338. ; and decreases cyclically.  On entry:
  339. ;    AL = attribute
  340. ;    AH = intensity increase/palette (each palette's RGB values
  341. ;         will be this much higher than the previous palette's)
  342. ;    CH = base palette
  343. ;    CL = terminal palette
  344. ; The color definition in palette CH is unaffected; palettes CH+1..CL
  345. ; will contain augmented color definitions.  Function does nothing
  346. ; if CL >= CH.
  347. ;
  348. ; AX destroyed.  New palettes not loaded into VGA.
  349. ;
  350. pulse_color_partial:
  351.  
  352.         push bx
  353.         push cx
  354.         push si
  355.         push di
  356.  
  357. ; Verify the palette numbers
  358.         cmp ch,15                       ; CH > 15?
  359.         ja P90                          ; Yes
  360.         cmp cl,ch                       ; CL >= CH?
  361.         jae P90                         ; Yes
  362.  
  363. ; Address the base definition (palette CL) for this attribute
  364.         call get_DAC_ptr
  365.         mov si,bx                       ; SI -> first definition
  366.         sub ch,cl                       ; CH = # of palettes affected
  367.         mov cl,ch
  368.         xor ch,ch                       ; Now CX
  369.  
  370.  
  371. ; Loop through the required number of palettes
  372. p_palette_loop:
  373.             push cx
  374.             mov cx,3
  375.             mov di,si                   ; SI/DI -> color def, crnt palette
  376.             add di,16*3                 ; DI -> color def, next palette
  377. p_RGB_loop:
  378.                 lodsb                   ; Get R/G/B intensity, crnt pal
  379.                 or al,al                ; Don't increment missing primaries
  380.                 jz P10
  381.                     add al,ah           ; Add per-palette increment
  382.                     cmp al,63           ; Don't let it go past 63
  383.                     jbe P10
  384.                     mov al,63
  385. P10:            stosb                   ; Store increment value in next pal
  386.                 loop p_RGB_loop         ; Loop for 3 primaries
  387.             pop cx
  388.             add si,16*3-3               ; Next palette
  389.         loop p_palette_loop
  390.  
  391. P90:
  392.         pop di
  393.         pop si
  394.         pop cx
  395.         pop bx
  396.         ret
  397.  
  398. ; ----- pulse_color -----------------------------------------------------
  399. ; Identical to pulse_color_partial except that a full range 0-15 is used;
  400. ; reg CX input not required.
  401. ;
  402. ; Entry: see pulse_color_partial; CH/CL not required.
  403. ;
  404. ; AX destroyed.  New palettes not loaded into VGA.
  405. ;
  406. pulse_color:
  407.  
  408.         push cx
  409.         mov cx,0F00H
  410.         call pulse_color_partial
  411.         pop cx
  412.         ret
  413.  
  414.  
  415. ; ----- set_color_partial --------------------------------------------
  416. ; This function sets the color definitions for attribute AL in palettes
  417. ; CL to CH to the 3-byte RGB definition at DS:SI.  Ensure that CH >= CL
  418. ; and that both are in the range 0..15.  The new palette is not sent to
  419. ; the VGA.
  420. ;
  421. ; The function does nothing if CL > CH or either is not in the range
  422. ; 0-15.
  423. ;
  424. ; AX destroyed.
  425. ;
  426. set_color_partial:
  427.  
  428.         push bx
  429.         push cx
  430.         push si
  431.         push di
  432.  
  433. ; Verify the palette numbers
  434.         cmp ch,15                       ; CH > 15?
  435.         ja S10                          ; Yes
  436.         cmp cl,ch                       ; CL >= CH?
  437.         ja S10                          ; Yes
  438.  
  439. ; Address the base definition (palette CL) for this attribute
  440.         call get_DAC_ptr
  441.         mov di,bx                       ; DI -> first definition
  442.         inc ch
  443.         sub ch,cl                       ; CH = # of palettes affected
  444.         mov cl,ch
  445.         xor ch,ch                       ; Now CX
  446.  
  447. ; Loop through the required number of palettes
  448. sc_palette_loop:
  449.             push si                     ; Copy def from SI to palette n
  450.             lodsb
  451.             stosb
  452.             lodsw
  453.             stosw
  454.             pop si
  455.             add di,16*3-3               ; DI -> color def in pal n+1
  456.         loop sc_palette_loop
  457.  
  458. S10:
  459.         pop di
  460.         pop si
  461.         pop cx
  462.         pop bx
  463.         ret
  464.  
  465. ; ----- set_color --------------------------------------------------
  466. ; Identical to set_color_partial, except that the full range of
  467. ; palettes (0..15) is assumed.  I.e., this function defines all palettes
  468. ; for attribute AL to contain the RGB color definition at DS:SI.
  469. ; Reg CX input not required.
  470. ;
  471. set_color:
  472.         push cx
  473.         mov cx,0F00h
  474.         call set_color_partial
  475.         pop cx
  476.         ret
  477.  
  478. ; ----- grade_color_partial ------------------------------------------
  479. ; This function creates a graded set of colors for attribute AL.
  480. ; CL contains a starting palette (0-14) and CH contains an ending
  481. ; palette (1-15, CH > CL).
  482. ;
  483. ; DS:SI points to the "terminal" color definition, which will be
  484. ; the definition in palette CH.  On exit, palettes CL-CH will contain
  485. ; "graded" color definitions for the attribute, so that the displayed
  486. ; color will change slowly from the base color (in palette CL) to the
  487. ; terminal color (in palette CH).  The color definition at DS:SI
  488. ; is three bytes long (one byte each for R, G, B intensity).  RGB
  489. ; values are modulated into the range 0-63.  The new palette is not
  490. ; sent to the VGA.  AX destroyed.
  491. ;
  492. ; The function does nothing if CL >= CH or either is not in the range
  493. ; 0-15.
  494. ;
  495. grade_color_partial:
  496.  
  497.         push bx
  498.         push cx
  499.         push si
  500.         push di
  501.  
  502. ; Verify the palette numbers
  503.         cmp ch,15                       ; CH > 15?
  504.         ja G10                          ; Yes
  505.         cmp cl,ch                       ; CL >= CH?
  506.         jae G10                         ; Yes
  507.  
  508. ; Address the base definition (palette CL) for this color
  509.         call get_DAC_ptr
  510.         push bx
  511.         sub ch,cl                       ; CH = # of palettes graded
  512.         mov cl,ch
  513.         xor ch,ch                       ; Now CX
  514.         mov di,offset red_scale
  515.         call calc_scale_factors         ; Calc red scaling factors
  516.         call calc_scale_factors         ;  "   grn   "       "
  517.         call calc_scale_factors         ;  "   blue  "       "
  518.         pop si                          ; SI -> initial definition
  519.  
  520. ; Loop through the required number of palettes
  521. gc_palette_loop:
  522.             mov di,si                   ; SI/DI -> color def in palette n
  523.             add di,16*3                 ; DI -> color def in pal n+1
  524.  
  525.             ; Augment RGB values for this video DAC color register
  526.             mov bx,offset red_scale     ; Point to red scale factors
  527.             call increment              ; Scale red
  528.             call increment              ; Scale green
  529.             call increment              ; Scale blue
  530.  
  531.             add si,16*3-3               ; Next palette
  532.             loop gc_palette_loop
  533.  
  534. G10:
  535.         pop di
  536.         pop si
  537.         pop cx
  538.         pop bx
  539.         ret
  540.  
  541. ; ----- grade_color --------------------------------------------------
  542. ; This is the same as GRADE_COLOR_PARTIAL, except that a full 15-palette
  543. ; grade is automatic.  Reg CX input is not required.
  544. ;
  545.  
  546. grade_color:
  547.         push cx
  548.         mov cx,0F00h                    ; Grade palettes 0-15
  549.         call grade_color_partial
  550.         pop cx
  551.         ret
  552.  
  553. ; ----- blinker --------------------------------------------------
  554. ; This function creates a simulated "blinking" color for attribute
  555. ; AL.  Unlike most of the other functions, this one works with a
  556. ; full 8-bit attribute (bits 0-3=FG, 4-7=BG, as usual).  "Blinking"
  557. ; is accomplished by putting the BG color definition into palettes
  558. ; 8-15 for the selected FG color.
  559. ;
  560. ; Note that palettes 0-7 are not altered, so you can do whatever
  561. ; you want with the "visible" half of the blink text (like scaling it,
  562. ; as is done in the "softened blinking" demo.
  563. ;
  564. ; AX destroyed.  New palette not sent to VGA.
  565. ;
  566. blinker:
  567.         push bx
  568.         push cx
  569.  
  570. ; Get a pointer to the color definition for the BG attribute
  571.         push ax
  572.         mov cl,4                        ; Mov high nibble (BG) to low
  573.         shr al,cl
  574.         xor cl,cl                       ; Get ptr to def in palette 0
  575.         call get_DAC_ptr
  576.         mov si,bx                       ; SI->BG def, palette 0
  577.         pop ax
  578.  
  579. ; Now do a SET_COLOR for the FG attribute in palettes 8-15,
  580. ; using the color definition at DS:SI (which is the BG color)
  581.         and al,0FH                      ; Mask the BG attribute number
  582.         mov cx,0F08h                    ; Palettes 8-15
  583.         call set_color_partial
  584.  
  585.         pop cx
  586.         pop bx
  587.         ret
  588.  
  589. ; =======================================================================
  590. ;                             INTERNAL SUBROUTINES
  591. ; =======================================================================
  592.  
  593. ; ----- dupe_palette0 -----------------------------------------------
  594. ; This function creates 16 "standard" palettes in NEWPALS.
  595. ; The palettes are not loaded into the VGA.
  596. ; Regs used: AX,CX,SI,DI
  597. ;
  598. dupe_palette0:
  599.         ; Copy the base palette into palette 0 of newpals.  Each color
  600.         ; register contains 3 colors (R, G, and B), so the full palette
  601.         ; is 16*3 bytes long
  602.         mov si,offset new_base_pal
  603.         mov di,offset newpals
  604.         mov cx,16*3/2                  ; 256 colors, 3 RGB values each
  605.         cld
  606.         rep movsw
  607.  
  608.         ; Now duplicate pallete 0 (colors 0-15) to pals 1-15 (colors 16-255)
  609.         ; We simplify this by allowing the copies to overlap.
  610.         mov si,offset newpals           ; SI -> palette 0
  611.         mov di,offset newpals+16*3      ; DI -> palette 1
  612.         mov cx,15*16*3/2                ; 15 pals, 16 colors each, @ 3 bytes
  613.         rep movsw
  614.  
  615.         ret
  616.  
  617.  
  618. ; ----- calc_scale_factors ---------------------------------------------
  619. ; This function generates the parameters for scaling a color from
  620. ; an initial value to a terminal value.  On entry, DS:BX points
  621. ; to an initial color value (0-63), DS:SI points to a terminal
  622. ; color value (0-63), and ES:DI points to a 3-byte interpolation
  623. ; factor storage area.  The function calculates the numbers needed
  624. ; to scale the color from the initial definition to the terminal
  625. ; definition over a span of CL palettes (normally 15).
  626. ;
  627. ; The 3-byte factor storage area is filled as follows:
  628. ;       byte signed integer: increment/palette
  629. ;       byte unsigned integer: number of extra increments required
  630. ;       byte signed integer: excess increment value (1 or -1)
  631. ;
  632. ; To scale a palette, start with palette 0 and add the increment/palette
  633. ; to each succeeding palette.  Also add the excess increment value (1 or -1)
  634. ; to the first n palettes (1-n), where n is the number of extra increments.
  635. ; For example, if the initial color value is 21 and the terminal is 63, the
  636. ; factor storage area would contain 2,12,1.  To scale from 21 to 63, start
  637. ; with the value in palette 0 and add 3 per palette (2+1) from 1-12 and two
  638. ; per palette from 13-15:
  639. ;       0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
  640. ;       21 24 27 30 33 36 39 42 45 48 51 54 57 59 61 63
  641. ; (Everything in the above assumes a 15-palette scale).
  642. ;
  643. ; On exit, BX and SI have been incremented by one, and DI by 3.  This
  644. ; conveniently points to the next color values and factor storage area.
  645. ; Other regs are preserved.
  646. ;
  647. calc_scale_factors:
  648.  
  649. ; Make sure CL is OK
  650.         and cl,0FH
  651.         or cl,cl
  652.         jnz CSF10
  653.           mov cl,15
  654. CSF10:
  655.  
  656. ; Get the initial color to AH and terminal color to AL
  657.         mov al,[bx]                     ; Initial color value
  658.         inc bx
  659.         mov ah,al
  660.         lodsb                           ; Terminal color value
  661.         and al,3FH                      ; Force 0-63
  662.  
  663. ; Compute increment/palette and number of excess increments needed
  664.         sub al,ah                       ; AL = difference (term-init)
  665.         cbw
  666.         idiv cl                         ; AL = inc/pal, AL = excess
  667.         mov [di.incr],al                ; Store increment/palette
  668.  
  669. ; Decide whether the excess increment value is +1 or -1.  It will be
  670. ; -1 if the "excess" calculated above is negative; the excess count will
  671. ; also have to be made positive, if so.
  672.         mov al,1                        ; Assume positive
  673.         or ah,ah                        ; Is it negative?
  674.         jns I1                          ; No, continue
  675.           neg al                        ; Yes, make increment negative
  676.           neg ah                        ; And count positive
  677. I1:     mov [di.xs_count],ah            ; Store the values
  678.         mov [di.xs_incr_val],al
  679.         add di,type scale_factors       ; Next storage area
  680.  
  681.         ret
  682.  
  683. ; ----- increment -----------------------------------------------------
  684. ; This subfunction increments a color value from palette n to palette
  685. ; n+1 using the scale factors at DS:BX (see CALC_SCALE_FACTORS).
  686. ; Entry: DS:BX->scale factors, DS:SI->palette n color value,
  687. ; ES:DI -> palette n+1 color value.  On exit, SI has been incremented
  688. ; (to point to the next color value), and BX is increased by 3 (to point
  689. ; to the next scale factor storage area).  The xs_incr field of the
  690. ; scale factor record is decremented if not already zero.
  691. ;
  692. increment:
  693.             lodsb                       ; Get original R/G/B value
  694.             add al,[bx.incr]            ; Add per-palette increment
  695.             test [bx.xs_count],-1       ; Any excess increments left?
  696.             jz no_rem                   ; No
  697.               dec [bx.xs_count]         ; Yes, dec remaining excess count
  698.               add al,[bx.xs_incr_val]   ; And add the excess incrmt (1/-1)
  699. no_rem:
  700.             stosb                       ; Store the graded value
  701.             add bx,type scale_factors
  702.             ret
  703.  
  704. ; ----- set_colors --------------------------------------------------
  705. ; This function sets the 256 video DAC color registers from the table
  706. ; at ES:DX, i.e., it loads the 256 colors definitions into the VGA.
  707. ;
  708. set_colors:
  709.         push ax
  710.         push bx
  711.         push cx
  712.         xor bx,bx                       ; Start with register 0
  713.         mov cx,256                      ; 256 colors
  714.         palctrl _SET_DACS
  715.         pop cx
  716.         pop bx
  717.         pop ax
  718.         ret
  719.  
  720.  
  721. ; ----- get_DAC_ptr ----------------------------------------------
  722. ; Returns a pointer in BX to the color definition for attribute AL
  723. ; in palette CL of NEWPALS.  Other regs preserved.
  724. ;
  725. get_DAC_ptr:
  726.         push ax
  727.         and ax,0FH                      ; Ensure range 0-15
  728.         mov bx,ax
  729.         mov al,newpalregs[bx]           ; Get palreg for this attrib
  730.         mov bx,ax                       ; Triple it for offset into color tab
  731.         shl bx,1
  732.         add bx,ax                       ; BX = 3 * color #
  733.         mov al,16*3                     ; Bytes/palette
  734.         mul cl                          ; AX -> offset of palette CL
  735.         add bx,ax                       ; BX -> offset of color def in NEWPALS
  736.         add bx,offset newpals           ; BX -> base color definition
  737.         pop ax
  738.         ret
  739.  
  740. ; =======================================================================
  741. ;                               TIMER INTERCEPT
  742. ; =======================================================================
  743.  
  744. Comment |
  745.   This is the timer intercept.  On each timer tick, we decrement the
  746.   countdown (if we are enabled).  If the count goes to zero, we go to
  747.   the next palette.  The next palette is determined by the current
  748.   palette (in pal_select) and the delta value; delta is added to
  749.   the current value and range checked.  If the new palette is out of
  750.   range, it's brought in range and the sign of delta is changed.
  751. |
  752.  
  753. timer_int:
  754.         assume cs:code,ds:nothing,es:nothing
  755.  
  756. ; Is the flasher enabled?
  757.         test flash_enabled,-1
  758.         jz timer9                       ; No
  759.  
  760. ; Dec count, skip rest if nonzero
  761.         dec count
  762.         jnz timer9
  763.  
  764. ; Count has zeroed, switch palettes by adding the delta.  If the
  765. ; palette number goes out of range, reverse the sign of the delta
  766. ; and bring the palette number back into range.  PAL_SELECT has
  767. ; the current palette number.
  768.         push ax
  769.         push bx
  770.  
  771.         mov bh,pal_select               ; Get current palette
  772.  
  773.         add bh,delta                    ; Add the delta
  774.         js P2                           ; Go if new palette not negative
  775.  
  776. P1:     cmp bh,15                       ; Check for positive out-of-range
  777.         jbe pal_OK                      ; It's OK
  778. P2:       neg delta                     ; Reverse the direction
  779.           add bh,delta
  780.           add bh,delta
  781.  
  782. pal_OK:
  783.         mov pal_select,bh               ; Save new palette
  784. if USE_BIOS
  785. ; Use BIOS to set color select register (palette)
  786.         mov bl,1                        ; And send it to the VGA
  787.         palctrl _SET_ATR_SELECT_STATE
  788. else
  789. ; Use register-level programming of the attribute control reg (ACR)
  790.         push dx
  791.  
  792.         ; Get port address of CRT status register
  793.         xor ax,ax
  794.         push ds
  795.         mov ds,ax
  796.         mov dx,ds:[463h]                ; DX = 3x8 register
  797.         pop ds
  798.         add dx,6                        ; DX = 3xA, CRT status reg
  799.  
  800.         ; Wait for a retrace
  801.         push cx
  802.         mov ah,5
  803.         xor cx,cx
  804. t_wait:     in al,dx
  805.             test al,8
  806.             jnz t_go
  807.             loop t_wait
  808.             dec ah
  809.             jnz t_wait
  810. t_go:   pop cx
  811.  
  812.         ; Do rest with ints off
  813.         pushf
  814.         cli
  815.  
  816.         ; Set color select
  817.         in al,dx                        ; Set addr/data flipflop in ACR
  818.         push dx                         ; Save CRT status reg port #
  819.  
  820.         mov dx,3C0H                     ; Select ACR reg 14h (color select)
  821.         mov al,14h
  822.         out dx,al
  823.         jmp $+2
  824.  
  825.         mov al,bh                       ; Send color select data
  826.         out dx,al
  827.  
  828.         pop dx                          ; Recover CRT status reg
  829.         in al,dx                        ; Reset flipflop
  830.         mov dx,3C0h                     ; ACR again
  831.         mov al,20h                      ; Restore palette
  832.         out dx,al
  833.  
  834.         popf                            ; Ints back on
  835.  
  836.         pop dx
  837. endif
  838.  
  839.         mov ax,flash_reset_count        ; Reset the count
  840.         mov count,ax
  841.  
  842.         pop bx
  843.         pop ax
  844.  
  845. ; Done, go do the real timer routine
  846. timer9:
  847.         jmp oldtimer
  848.  
  849. code ends
  850. end
  851.